Transferring Images with TransparentBlt

Level: Intermediate

Janet Terra

by

janetterra@yahoo.com

Home

Container Control

API Dialogs

Place a Dialog

Center a Dialog

LB IDE

Close Multiple Windows

TransparentBlt

Animation Control

Sprite Byte

Qcard DLL

Patterns and Music

Newsletter help

Index

A Transparent Background for Static Graphics

Do you find yourself creating sprites, not for animation, but to draw static images with a transparent background? If you do, then consider using the API TransparentBlt function in MSIMG32.DLL. The MSIMG32.DLL is included with all versions of Window 98 and later. Sorry, Windows 95 Users, this doesn't include you, although you may be able to download the DLL. The TransparentBlt coding is very similar to the BitBlt and StretchBlt functions of GDI32.DLL. If you are unfamiliar with transferring bits using BitBlt, please read [Bitmaps the Fast Way (Newsletter 122)] by Callum Lowcay. This is an excellent article demonstrating how BitBlt works.

TransparentBlt, Windows 95 and Windows 98

If you are using Windows 95 or Windows 98, please read carefully.

From [support.microsoft.com]:

SYMPTOMS

When you are running software that calls the TransparentBlt() function on Windows 95 or Windows 98, the software may exhaust the available system resources and stop responding. This problem is most evident in applications that call TransparentBlt() frequently.

CAUSE

The implementation of the TransparentBlt() function in the Msimg32.dll file contains a leak that exhausts system resources.

RESOLUTION

Instead of using TransparentBlt(), use the code that is provided in the following Microsoft Knowledge Base article: [HOW TO: Draw Transparent Bitmaps]

The referred code describes how to mask an image using BitBlt and the XOR rastor operation. Microsoft states this problem was solved with Windows ME and later versions. You can also use GDI32.DLL to create masked images. See [Sprite in a Box (Newsletter 108)] by Alyce Watson.

Finding, Opening and Closing the DLL

There is no need to include a separate MSIMG32.DLL file with programs calling this DLL if your operating system is Windows 98 or later. You will need to OPEN the DLL. Common Windows operating system DLL's do not need to be OPENed before calling. These common DLL's include USER32.DLL, KERNEL32.DLL, GDI32.DLL, WINMM.DLL, SHELL32.DLL, COMDLG32.DLL, COMCTL32.DLL. MSIMG32.DLL DOES REQUIRE OPENing before CALLing.

Open msimg32.dll for DLL as #m

As with all OPENed DLL's, the DLL must be closed before exiting the program.

Close #m

BitBlt, StretchBlt, TransparentBlt: A Quick Comparison

CapabilitiesBitBltTransparentBltStretchBlt
Simple bitcopyYesYesYes
Bitcopy from memory deviceYes YesYes
ResizeNo YesYes
Raster OperationsYes NoYes
FlipNoNoYes
MirrorNoNoYes
Rotate 180 degreesNoNo Yes
Assign Color TransparentNoYes No

The Demo Bitmap: cherry.bmp

These two demos use the bitmap cherry.bmp, found in the bmp folder of the Liberty BASIC directory. If the following codes are not run from your main Liberty BASIC directory, you may have to redefine the path. The demos are based upon the white background of cherry.bmp. If you choose to substitute with a bitmap with a different background color, change the long number value of white (16777215) to the long number value of the desired color.

Demo 1: Drawbmp vs TransparentBlt

'Demo Drawing Bitmaps with Transparent Backgrounds
'Using msimg32.dll and TransparentBlt
'Copyright Janet Terra December 2004
'This information is free for anyone to use in your program
'but this demo itself may not be copied 'as is' and reposted

'Users of PRE WINDOWS 98, please note:
'The msimg32.dll may not be available for Windows 95
'If running this program gives you - Runtime Error: The
'specified module could not be found. (OS error 16r7E)
'then msimg32.dll is not present on your computer.

'In addition, memory leaks have been associated with
'repeated TransparentBlt calls and Windows 95/98
'Visit http://support.microsoft.com for more info

    Nomainwin
    WindowWidth = 388
    WindowHeight = 400

'Define 6 Graphicboxes: 1,2,3 = Drawbmp, 4,5,6 = TransparentBlt
    Graphicbox #w.g1, 10, 10, 100, 100
    Statictext #w.stxt1a, "Drawbmp cherry 5, 10", 8, 120, 110, 16
    Statictext #w.stxt1b, "white background", 8, 136, 110, 16
    Graphicbox #w.g2, 140, 10, 100, 100
    Statictext #w.stxt2a, "Drawbmp cherry 5, 10", 138, 120, 110, 16
    Statictext #w.stxt2b, "blue background", 138, 136, 110, 16
    Graphicbox #w.g3, 270, 10, 100, 100
    Statictext #w.stxt3a, "Drawbmp cherry 5, 10", 268, 120, 110, 16
    Statictext #w.stxt3b, "patterned background", 268, 136, 110, 16
    Graphicbox #w.g4, 10, 190, 100, 100
    Statictext #w.stxt4a, "Using TransparentBlt", 8, 300, 110, 16
    Statictext #w.stxt4b, "white background", 8, 316, 110, 16
    Statictext #w.stxt4c, "same width and height", 8, 332, 110, 16
    Graphicbox #w.g5, 140, 190, 100, 100
    Statictext #w.stxt5a, "Using TransparentBlt", 138, 300, 110, 16
    Statictext #w.stxt5b, "blue background", 138, 316, 110, 16
    Statictext #w.stxt5c, "smaller width and height (shrink)", 138, 332, 110, 32
    Graphicbox #w.g6, 270, 190, 100, 100
    Statictext #w.stxt6a, "Using TransparentBlt", 268, 300, 110, 16
    Statictext #w.stxt6b, "patterned background", 268, 316, 110, 16
    Statictext #w.stxt5c, "larger width and height (stretch)", 268, 332, 110, 32

'Load a bitmap.  This demo uses cherry.bmp found in the bmp folder of the
'Liberty BASIC folder.  This demo must be run from the main Liberty BASIC
'program folder in order to find cherry.bmp properly.
    Loadbmp "cherry", DefaultDir$;"\bmp\cherry.bmp"

'Open the Window
    Open "Demo" For Window as #w
    #w, "Trapclose [endProgram]"

'Obtain the handles of the primary window, the source window or graphicbox,
'and the destination windows or graphicboxes.  In this demo, the first graphicbox
'(the bitmap drawn against a white background) also serves as the source bitmap)

    hW = hWnd(#w) 'Window handle
    hWG1 = hWnd(#w.g1) 'Source Handle
    hWG4 = hWnd(#w.g4) 'Destination Handle (#w.g4)
    hWG5 = hWnd(#w.g5) 'Destination Handle (#w.g5)
    hWG6 = hWnd(#w.g6) 'Destination Handle (#w.g6)
    hDC1 = GetDC(hWG1) 'Source Device Control
    hDC4 = GetDC(hWG4) 'Destination Device Context (#w.g4)
    hDC5 = GetDC(hWG5) 'Destination Device Context (#w.g5)
    hDC6 = GetDC(hWG6) 'Destination Device Context (#w.g6)

'Open the msimg32.dll
    Open "msimg32.dll" for DLL as #m

'Display White, Blue and Patterned Backgrounds
    Call hueBackground "White", "#w.g1"
    Call hueBackground "Darkblue", "#w.g2"
    Call patternedBackground "#w.g3"
    Call hueBackground "White", "#w.g4"
    Call hueBackground "Darkblue", "#w.g5"
    Call patternedBackground "#w.g6"

'Draw the bitmap in the first graphicbox.  Remember this also serves as the
'source bitmap.
    #w.g1, "Drawbmp cherry 5, 10"

'Draw the bitmap in the second graphicbox.  The white rectangular background
'of the cherry remains present
    #w.g2, "Drawbmp cherry 5, 10"

'Draw the bitmap in the third graphicbox.  Again, the white rectangular
'background of the bitmap obscures the patterned background
    #w.g3, "Drawbmp cherry 5, 10"

'Assign ONE color to be the transparent color.  Remember you must use the
'long number.  In this case, the RGB of White is "255 255 255", so the
'long number is 255 + 255*256 + 255*256*256 or 16777215
    transpColor = 16777215

'Function variables are (DestinationDC, DestinationUpperLeftX, DestinationUpperLeftY,
'DestinationWidth, DestinationHeight, SourceDC, SourceUpperLeftX,
'SourceUpperLeftY, SourceWidth, SourceHeight, TransparentColor)

'Using the SAME Width and Height as the Source
    null = TransparentBlt(hDC4, 5, 10, 88, 65, hDC1, 5, 10, 88, 65, 16777215)

'Using a SMALLER Width and Height as the Source (Destination x and y are also changed)
    null = TransparentBlt(hDC5, 20, 20, 66, 48, hDC1, 5, 10, 88, 65, 16777215)

'Using a LARGER Width and Height as the Source (Destination x and y are also changed)
    null = TransparentBlt(hDC6, -10, 0, 132, 98, hDC1, 5, 10, 88, 65, 16777215)

Wait

    Sub hueBackground hue$, handle$
        #handle$, "Down; Fill ";hue$
        #handle$, "Flush; Discard"
    End Sub

    Sub patternedBackground handle$
        colorStrand$ = "Yellow Blue Darkgreen Darkblue Darkpink"
        colorCode = 0
        #handle$, "Down"
        For ii = 1 to 100
            colorCode = colorCode + 1
                If colorCode = 6 Then
                    colorCode = 1
                End If
            colorCode$ = Word$(colorStrand$, colorCode)
            #handle$, "Color ";colorCode$
            #handle$, "Line ";ii;" 0 ";ii;" 100"
        Next ii
        #handle$, "Flush; Discard"
    End Sub

[endProgram]
'Release memory from any device contexts created during program
    null = ReleaseDC(hWG1, hDC1)
    null = ReleaseDC(hWG4, hDC4)
    null = ReleaseDC(hWG5, hDC5)
    null = ReleaseDC(hWG6, hDC6)
'Close msimg32.dll
    Close #m
'Unload bitmap
    Unloadbmp "cherry"
'Close window
    Close #w
'End program
    End

'====================================================================
'These 3 Functions obtained from Liberty BASIC Workshop (c) Alyce Watson and used with permission of Alyce Watson
    Function TransparentBlt(hdcDest, xDest, yDest, wDest, hDest, hdcSource, xSource, ySource, wSource, hSource, clrTransp)
        Calldll #m, "TransparentBlt",_
        hdcDest as long,_        'handle to destination DC
        xDest as long,_   'x-coord of destination upper-left corner
        yDest as long,_   'y-coord of destination upper-left corner
        wDest as long,_     'width of destination rectangle
        hDest as long,_    'height of destination rectangle
        hdcSource as long,_         'handle to source DC
        xSource as long,_    'x-coord of source upper-left corner
        ySource as long,_    'y-coord of source upper-left corner
        wSource as long,_      'width of source rectangle
        hSource as long,_     'height of source rectangle
        clrTransp as ulong,_ 'color to make transparent
        result as boolean
    End Function

    Function GetDC(hwin)
        CallDLL #user32, "GetDC",hwin As long,GetDC as ulong
    End Function

    Function ReleaseDC(hwin, hdc)
        CallDLL #user32, "ReleaseDC",hwin As long,hdc As long,ReleaseDC As long
    End Function
'====================================================================

Demo 2: BitBlt, TransparentBlt and Drawing in Memory

If you haven't done so already, please read [Drawing IN MEMORY (Newsletter 101)] by Alyce Watson . There you'll find all the theory you need to understand that you can transfer an image drawn in memory but you can't transfer an image drawn in a hidden graphic box. This second demo demonstrates loading the cherry.bmp image in memory and then transferring that image to a graphicbox using both BitBlt and TransparentBlt.

'Demo Drawing Bitmaps with Transparent Backgrounds
'Using msimg32.dll and TransparentBlt
'Copyright Janet Terra December 2004
'This information is free for anyone to use in your program
'but this demo itself may not be copied 'as is' and reposted

'Users of PRE WINDOWS 98, please note:
'The msimg32.dll may not be available for Windows 95
'If running this program gives you - Runtime Error: The
'specified module could not be found. (OS error 16r7E)
'then msimg32.dll is not present on your computer.
'In addition, memory leaks have been associated with
'repeated TransparentBlt calls and Windows 95/98
'Visit http://support.microsoft.com for more info

    Nomainwin
    WindowWidth = 388
    WindowHeight = 400

'Define 6 Graphicboxes: 1,2,3 = Drawbmp, 4,5,6 = TransparentBlt
    Graphicbox #w.g1, 10, 10, 100, 100
    Statictext #w.stxt1a, "Drawbmp cherry 5, 10", 8, 120, 110, 16
    Statictext #w.stxt1b, "white background", 8, 136, 110, 16
    Graphicbox #w.g2, 140, 10, 100, 100
    Statictext #w.stxt2a, "Drawbmp cherry 5, 10", 138, 120, 110, 16
    Statictext #w.stxt2b, "blue background", 138, 136, 110, 16
    Graphicbox #w.g3, 270, 10, 100, 100
    Statictext #w.stxt3a, "Drawbmp cherry 5, 10", 268, 120, 110, 16
    Statictext #w.stxt3b, "patterned background", 268, 136, 110, 16
    Graphicbox #w.g4, 10, 190, 100, 100
    Statictext #w.stxt4a, "Using TransparentBlt", 8, 300, 110, 16
    Statictext #w.stxt4b, "white background", 8, 316, 110, 16
    Statictext #w.stxt4c, "same width and height", 8, 332, 110, 16
    Graphicbox #w.g5, 140, 190, 100, 100
    Statictext #w.stxt5a, "Using TransparentBlt", 138, 300, 110, 16
    Statictext #w.stxt5b, "blue background", 138, 316, 110, 16
    Statictext #w.stxt5c, "smaller width and height (shrink)", 138, 332, 110, 32
    Graphicbox #w.g6, 270, 190, 100, 100
    Statictext #w.stxt6a, "Using TransparentBlt", 268, 300, 110, 16
    Statictext #w.stxt6b, "patterned background", 268, 316, 110, 16
    Statictext #w.stxt5c, "larger width and height (stretch)", 268, 332, 110, 32

'Load a bitmap.  This demo uses cherry.bmp found in the bmp folder of the
'Liberty BASIC folder.  This demo must be run from the main Liberty BASIC
'program folder in order to find cherry.bmp properly.
    Loadbmp "cherry", DefaultDir$;"\bmp\cherry.bmp"

'Open the Window
    Open "Demo" For Window as #w
    #w, "Trapclose [endProgram]"

'Obtain the handles of the primary window, the source window or graphicbox,
'and the destination windows or graphicboxes.  In this demo, the first graphicbox
'(the bitmap drawn against a white background) also serves as the source bitmap)

    hW = hWnd(#w) 'Window handle
    hWG1 = hWnd(#w.g1) 'Source Handle
    hWG4 = hWnd(#w.g4) 'Destination Handle (#w.g4)
    hWG5 = hWnd(#w.g5) 'Destination Handle (#w.g5)
    hWG6 = hWnd(#w.g6) 'Destination Handle (#w.g6)
    hDC1 = GetDC(hWG1) 'Source Device Control
    hDC4 = GetDC(hWG4) 'Destination Device Context (#w.g4)
    hDC5 = GetDC(hWG5) 'Destination Device Context (#w.g5)
    hDC6 = GetDC(hWG6) 'Destination Device Context (#w.g6)

'Open the msimg32.dll
    Open "msimg32.dll" for DLL as #m

'Display White, Blue and Patterned Backgrounds
    Call hueBackground "White", "#w.g1"
    Call hueBackground "Darkblue", "#w.g2"
    Call patternedBackground "#w.g3"
    Call hueBackground "White", "#w.g4"
    Call hueBackground "Darkblue", "#w.g5"
    Call patternedBackground "#w.g6"

'Draw the bitmap in the first graphicbox.  Remember this also serves as the
'source bitmap.
    #w.g1, "Drawbmp cherry 5, 10"

'Draw the bitmap in the second graphicbox.  The white rectangular background
'of the cherry remains present
    #w.g2, "Drawbmp cherry 5, 10"

'Draw the bitmap in the third graphicbox.  Again, the white rectangular
'background of the bitmap obscures the patterned background
    #w.g3, "Drawbmp cherry 5, 10"

'Assign ONE color to be the transparent color.  Remember you must use the
'long number.  In this case, the RGB of White is "255 255 255", so the
'long number is 255 + 255*256 + 255*256*256 or 16777215
    transpColor = 16777215

'Function variables are (DestinationDC, DestinationUpperLeftX, DestinationUpperLeftY,
'DestinationWidth, DestinationHeight, SourceDC, SourceUpperLeftX,
'SourceUpperLeftY, SourceWidth, SourceHeight, TransparentColor)

'Using the SAME Width and Height as the Source
    null = TransparentBlt(hDC4, 5, 10, 88, 65, hDC1, 5, 10, 88, 65, 16777215)

'Using a SMALLER Width and Height as the Source (Destination x and y are also changed)
    null = TransparentBlt(hDC5, 20, 20, 66, 48, hDC1, 5, 10, 88, 65, 16777215)

'Using a LARGER Width and Height as the Source (Destination x and y are also changed)
    null = TransparentBlt(hDC6, -10, 0, 132, 98, hDC1, 5, 10, 88, 65, 16777215)

Wait

    Sub hueBackground hue$, handle$
        #handle$, "Down; Fill ";hue$
        #handle$, "Flush; Discard"
    End Sub

    Sub patternedBackground handle$
        colorStrand$ = "Yellow Blue Darkgreen Darkblue Darkpink"
        colorCode = 0
        #handle$, "Down"
        For ii = 1 to 100
            colorCode = colorCode + 1
                If colorCode = 6 Then
                    colorCode = 1
                End If
            colorCode$ = Word$(colorStrand$, colorCode)
            #handle$, "Color ";colorCode$
            #handle$, "Line ";ii;" 0 ";ii;" 100"
        Next ii
        #handle$, "Flush; Discard"
    End Sub

[endProgram]
'Release memory from any device contexts created during program
    null = ReleaseDC(hWG1, hDC1)
    null = ReleaseDC(hWG4, hDC4)
    null = ReleaseDC(hWG5, hDC5)
    null = ReleaseDC(hWG6, hDC6)
'Close msimg32.dll
    Close #m
'Unload bitmap
    Unloadbmp "cherry"
'Close window
    Close #w
'End program
    End

'====================================================================
'These 3 Functions obtained from Liberty BASIC Workshop (c) Alyce Watson and used with permission of Alyce Watson
    Function TransparentBlt(hdcDest, xDest, yDest, wDest, hDest, hdcSource, xSource, ySource, wSource, hSource, clrTransp)
        Calldll #m, "TransparentBlt",_
        hdcDest as long,_        'handle to destination DC
        xDest as long,_   'x-coord of destination upper-left corner
        yDest as long,_   'y-coord of destination upper-left corner
        wDest as long,_     'width of destination rectangle
        hDest as long,_    'height of destination rectangle
        hdcSource as long,_         'handle to source DC
        xSource as long,_    'x-coord of source upper-left corner
        ySource as long,_    'y-coord of source upper-left corner
        wSource as long,_      'width of source rectangle
        hSource as long,_     'height of source rectangle
        clrTransp as ulong,_ 'color to make transparent
        result as boolean
    End Function

    Function GetDC(hwin)
        CallDLL #user32, "GetDC",hwin As long,GetDC as ulong
    End Function

    Function ReleaseDC(hwin, hdc)
        CallDLL #user32, "ReleaseDC",hwin As long,hdc As long,ReleaseDC As long
    End Function
'====================================================================

Flushing API Graphics

API draw graphics cannot be flushed using the native Liberty BASIC command flush. To make graphics persist, use the Getbmp-Drawbmp-Flush sequence as suggested by Alyce Watson in [Sprite in a Box (Newsletter 108)].

Suggestions for Using

TransparentBlt is certainly not meant to replace sprites and there are some drawbacks, most especially when used with Windows 95 and Windows 98. TransparentBlt does, however, serve as a very viable means of displaying static images against a patterned background.


Home

Container Control

API Dialogs

Place a Dialog

Center a Dialog

LB IDE

Close Multiple Windows

TransparentBlt

Animation Control

Sprite Byte

Qcard DLL

Patterns and Music

Newsletter help

Index